package cn.mazexal.examapi.services.provider;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.RandomUtil;
import cn.mazexal.examapi.dataware.SysPayConfigMapper;
import cn.mazexal.examapi.models.db.SysPayConfigDO;
import cn.mazexal.examapi.models.thirdpart.alipay.AlipayAppArgs;
import cn.mazexal.examapi.models.thirdpart.huawei.HuaweiPayArgs;
import cn.mazexal.examapi.models.thirdpart.huawei.HuaweiPayReq;
import cn.mazexal.examapi.models.thirdpart.huawei.HuaweiSignUtil;
import cn.mazexal.examapi.models.thirdpart.wxpay.WxPayConfigBO;
import cn.mazexal.examapi.models.thirdpart.wxpay.WxPayConstant;
import cn.mazexal.examapi.models.thirdpart.wxpay.WxpayAppArgs;
import cn.mazexal.examapi.utils.SpringContextUtil;
import com.alibaba.fastjson2.JSON;
import com.alipay.api.*;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.File;

/**
 * @author: Mazexal
 * Date: 2025/6/29
 */
@Component
@Slf4j
public class PayProvider {

    @Value("${alipay.gateway}")
    String alipayGateway;

    @Value("${alipay.timeoutExpress}")
    String alipayTimeoutExpress;

    @Value("${alipay.notifyUrl}")
    String alipayNotifyUrl;

    @Value("${alipay.returnUrl}")
    String alipayReturnUrl;

    @Value("${wxpay.notifyUrl}")
    String wxpayNotifyUrl;

    @Value("${huawei.notifyUrl}")
    String huaweiNotifyUrl;

    @Value("${alipay.appId}")
    String alipayAppId;

    @Value("${alipay.pid}")
    String alipayPid;

    @Value("${alipay.privateKey}")
    String alipayPrivateKey;

    @Resource
    private SysPayConfigMapper sysPayConfigMapper;


    public String getAlipayAppParams(AlipayAppArgs alipayAppArgs) {
        // 初始化 SDK
        AlipayClient alipayClient = getAlipayClient(alipayAppArgs.getAppId(), alipayAppArgs.getPrivateKey(), AlipayConstants.FORMAT_JSON, AlipayConstants.CHARSET_UTF8, alipayAppArgs.getAlipayPublicKey(), alipayAppArgs.getSignType());

        // 创建请求
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();

        // 请求体
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setSubject(alipayAppArgs.getSubject());
        model.setBody(alipayAppArgs.getBody());
        model.setOutTradeNo(alipayAppArgs.getOutTradeNo());
        model.setTimeoutExpress(alipayTimeoutExpress);
        model.setTotalAmount(alipayAppArgs.getTotalAmount());
        model.setPassbackParams(String.valueOf(alipayAppArgs.getConfigId()));

        // 商户风险联防参数 copy-zt1-替换
        // model.setBusinessParams(alipayBusinessParamsBuilder.build(httpRiskInfo));

        //------
        // 支付宝免密支付开关
//        Integer alipayNoPasswordSwitch = Convert.toInt(configBusinessDictService.getConfigDictValue(ConfigBusinessDictEnum.ALIPAY_NO_PASSWORD_SWITCH), 0);
//        if (BoolIntVal.True == alipayNoPasswordSwitch || isAlipayNoPassword) {
//            setAlipayNoPasswordSignParams(model);
//        }
        //------
        request.setBizModel(model);

        // 异步通知地址 notifyUrl: http://xx/api-notify/v1/pay/alipay
        request.setNotifyUrl(alipayNotifyUrl);

        if (SpringContextUtil.isDev()) {
            log.info("获取支付宝APP支付参数 model = {}; 异步通知地址 = {}", JSON.toJSONString(model), alipayNotifyUrl);
        }

        try {
            if (alipayClient == null) {
                throw new Exception("SDK 初始化失败");
            }

            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
            if (response.isSuccess()) {
                return response.getBody();
            }
            throw new Exception(JSON.toJSONString(response));
        } catch (Exception e) {
            log.error("支付宝 APP 支付提交失败", e);
        }
        return null;
    }

    private AlipayClient getAlipayClient(String appId, String privatekey, String format, String charset, String publicKey, String signType) {
        try {
            // 判断是否存在证书
            String certPath = String.format("/data/server/cert/%s", appId);
            File certDir = new File(certPath);
            if (certDir.exists() && certDir.isDirectory()) {
                CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
                // 支付宝网关地址
                certAlipayRequest.setServerUrl(alipayGateway);
//                log.info("getAlipayClient() 存在证书  支付宝网关地址={} appId={}", certAlipayRequest.getServerUrl(), appId);
                certAlipayRequest.setAppId(appId);
                certAlipayRequest.setPrivateKey(privatekey);
                certAlipayRequest.setFormat(format);
                certAlipayRequest.setCharset(charset);
                certAlipayRequest.setSignType(signType);
                certAlipayRequest.setCertPath(String.format("%s%s", certPath, "/app.crt"));
                certAlipayRequest.setAlipayPublicCertPath(String.format("%s%s", certPath, "/alipay.crt"));
                certAlipayRequest.setRootCertPath(String.format("%s%s", certPath, "/root.crt"));
                return new DefaultAlipayClient(certAlipayRequest);
            } else {
                return new DefaultAlipayClient(alipayGateway, appId, privatekey, AlipayConstants.FORMAT_JSON, AlipayConstants.CHARSET_UTF8, publicKey, signType);
            }

        } catch (AlipayApiException e) {
            log.error("创建支付宝 Client 失败", e);
        }
        return null;
    }

    /**
     * 获取微信 APP 支付参数
     *
     * @param wxpayAppArgs
     * @return
     */
    public String getWxpayAppParams(WxpayAppArgs wxpayAppArgs) {
        // 随机字符串
        String nonceStr = RandomUtil.randomString(32);

        WxPayUnifiedOrderRequest request = getWxPayUnifiedOrderRequest(wxpayAppArgs, nonceStr);

        try {
            WxPayConfig wxPayConfig = new WxPayConfig();
            wxPayConfig.setAppId(wxpayAppArgs.getAppId());
            wxPayConfig.setMchId(wxpayAppArgs.getMchId());
            wxPayConfig.setMchKey(wxpayAppArgs.getApiKey());
            wxPayConfig.setNotifyUrl(wxpayNotifyUrl);

            WxPayService wxPayService = new WxPayServiceImpl();
            wxPayService.setConfig(wxPayConfig);

            WxPayAppOrderResult result = wxPayService.createOrder(request);

            return com.alibaba.fastjson.JSON.toJSONString(result);
        } catch (Exception e) {
            log.error("微信支付创建失败", e);
            return null;
        }
    }

    @NotNull
    private WxPayUnifiedOrderRequest getWxPayUnifiedOrderRequest(WxpayAppArgs wxpayAppArgs, String nonceStr) {
        WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
        request.setDeviceInfo(WxPayConstant.DEVICE_INFO_DEFAULT);
        request.setFeeType(WxPayConstant.FEE_TYPE_CNY);
        request.setTradeType(WxPayConstants.TradeType.APP);
        request.setNotifyUrl(wxpayNotifyUrl);
        request.setBody(wxpayAppArgs.getBody());
        request.setDetail(wxpayAppArgs.getDetail());
        request.setNonceStr(nonceStr);
        request.setOutTradeNo(wxpayAppArgs.getOutTradeNo());
        request.setTotalFee(wxpayAppArgs.getTotalFee());
        request.setSignType(WxPayConstants.SignType.HMAC_SHA256);
        request.setSpbillCreateIp(wxpayAppArgs.getIp());
        request.setAttach(String.valueOf(wxpayAppArgs.getConfigId()));
        return request;
    }

    public boolean checkWxPayNotifySign(String xmlData) {
        try {
            WxPayOrderNotifyResult result = WxPayOrderNotifyResult.fromXML(xmlData);
            Long configId = Convert.toLong(result.getAttach());
            SysPayConfigDO sysPayConfigDO = sysPayConfigMapper.selectById(configId);

            if (sysPayConfigDO == null) {
                log.error("未找到微信支付配置:", configId);
                return false;
            }
            WxPayConfigBO payConfigWxDO = JSON.parseObject(sysPayConfigDO.getConfig(), WxPayConfigBO.class);

            String tradeType = result.getTradeType();
            if (tradeType.equals(WxPayConstants.TradeType.APP)) {
                com.github.binarywang.wxpay.config.WxPayConfig wxPayConfig = new com.github.binarywang.wxpay.config.WxPayConfig();
                wxPayConfig.setAppId(payConfigWxDO.getOpenAppId());
                wxPayConfig.setMchId(payConfigWxDO.getOpenMchId());
                wxPayConfig.setMchKey(payConfigWxDO.getOpenApiKey());

                WxPayService wxPayService = new WxPayServiceImpl();
                wxPayService.setConfig(wxPayConfig);
                result.checkResult(wxPayService, WxPayConstants.SignType.HMAC_SHA256, true);

                return true;
            } else if (tradeType.equals(WxPayConstants.TradeType.JSAPI) || tradeType.equals(WxPayConstants.TradeType.MWEB)) {
                com.github.binarywang.wxpay.config.WxPayConfig wxPayConfig = new WxPayConfig();
                wxPayConfig.setAppId(payConfigWxDO.getPublicAppId());
                wxPayConfig.setMchId(payConfigWxDO.getPublicMchId());
                wxPayConfig.setMchKey(payConfigWxDO.getPublicApiKey());

                WxPayService wxPayService = new WxPayServiceImpl();
                wxPayService.setConfig(wxPayConfig);

                result.checkResult(wxPayService, WxPayConstants.SignType.MD5, true);
                return true;
            }
        } catch (Exception e) {
            log.error("微信支付异步通知验签失败", e);
        }
        return false;
    }


    /**
     * 获取华为支付参数
     *
     * @param args
     * @return
     */
    public String getHuaweiPayParams(HuaweiPayArgs args) {
        HuaweiPayReq payReq = new HuaweiPayReq();
        payReq.setProductName(args.getProductName());
        payReq.setProductDesc((args.getProductDesc()));
        payReq.setApplicationID(args.getAppId());
        payReq.setRequestId(args.getRequestId());
        payReq.setAmount(args.getAmount());
        payReq.setMerchantId(args.getMerchantId());
        payReq.setMerchantName(args.getMerchantName());
        payReq.setServiceCatalog("X5");
        payReq.setSdkChannel("1");
        payReq.setUrl(huaweiNotifyUrl);
        payReq.setExtReserved(String.valueOf(args.getConfigId()));

        // 签名
        payReq.setSign(HuaweiSignUtil.signPayReq(payReq, args.getPrivateKey()));

        return com.alibaba.fastjson.JSON.toJSONString(payReq);
    }

}
